#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>
#include <sdktools>

#define PLUGIN_VERSION "1.0"


public Plugin myinfo =
{
	name = "l4d2_team_balance_fo",
	author = "豆瓣酱な",
	description = "智能平衡生还者与感染者人数，当生还者总数超过设定值时，自动将多余玩家移至感染者团队.",
	version = PLUGIN_VERSION,
	url = "https://gitee.com/sweet-and-sour-bombs/adfvsdsd"
};


ConVar g_cvMaxTotal;
int g_iLastTotalCount;

public void OnPluginStart() 
{
	g_cvMaxTotal = CreateConVar("l4d2_total_limit", "4", "生还者最大总人数", FCVAR_NONE, true, 1.0, true, 15.0);
	//AutoExecConfig(true, "l4d2_team_balance_fo");
    
	HookEvent("player_team", Event_TeamChange);
}

public void OnClientPutInServer(int client) 
{
	if(IsValidHuman(client)) 
	{
		CreateTimer(1.0, Timer_InitialCheck, GetClientUserId(client));
	}
}

public Action Event_TeamChange(Event event, const char[] name, bool dontBroadcast) 
{
	CreateTimer(0.5, Timer_DelayedBalance);
	return Plugin_Continue;
}

public Action Timer_InitialCheck(Handle timer, any userid) 
{
	int client = GetClientOfUserId(userid);
	if(IsValidHuman(client)) EnforceBalance();
	return Plugin_Continue;
}

public Action Timer_DelayedBalance(Handle timer) 
{
	EnforceBalance();
	return Plugin_Continue;
}

void EnforceBalance() 
{
	int currentTotal = CountTotalHumans();
	if(currentTotal == g_iLastTotalCount) return;
    
	g_iLastTotalCount = currentTotal;
	int maxTotal = g_cvMaxTotal.IntValue;
    
	if(currentTotal > maxTotal) 
	{
		int needMove = currentTotal - maxTotal;
		MoveWithNameNotify(needMove);
	}
}

void MoveWithNameNotify(int count) 
{
	char movedNames[256] = "";
	int moved;
    
	// 优先移动观察者
	for(int i = 1; i <= MaxClients && moved < count; i++) 
	{
		if(IsValidHuman(i) && GetClientTeam(i) == 1) 
		{
			char name[MAX_NAME_LENGTH];
			GetClientName(i, name, sizeof(name));
			Format(movedNames, sizeof(movedNames), "%s%s%s", movedNames, (moved==0)?"":"", name);
            
			ChangeClientTeam(i, 3);
			moved++;
		}
	}
    
	// 再移动生还者
	for(int i = 1; i <= MaxClients && moved < count; i++) 
	{
		if(IsValidHuman(i) && GetClientTeam(i) == 2) 
		{
			char name[MAX_NAME_LENGTH];
			GetClientName(i, name, sizeof(name));
			Format(movedNames, sizeof(movedNames), "%s%s%s", movedNames, (moved==0)?"":"", name);
            
			ChangeClientTeam(i, 3);
			moved++;
		}
	}
    
	if (strlen(movedNames) > 0) 
	{
		PrintToChatAll("\x04[系统]\x03%s\x04已被分配到\x03感染者\x04团队", movedNames);
	}
}

int CountTotalHumans() 
{
	int count;
	for(int i = 1; i <= MaxClients; i++) 
	{
		if(IsValidHuman(i) && (GetClientTeam(i) == 1 || GetClientTeam(i) == 2)) 
		{
			count++;
		}
	}
	return count;
}

bool IsValidHuman(int client) 
{
	return client > 0 && client <= MaxClients && IsClientInGame(client) && !IsFakeClient(client);
}